package com.kadron.item;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.faces.event.AbortProcessingException;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;
import javax.faces.model.SelectItem;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.transaction.Transaction;
import org.jboss.seam.transaction.UserTransaction;
import org.richfaces.event.FileUploadListener;
import org.richfaces.event.UploadEvent;
import org.richfaces.model.UploadItem;

import com.kadron.common.KConst;
import com.kadron.common.KIDGenerator;
import com.kadron.common.KInitParams;
import com.kadron.common.KUtil;
import com.kadron.dao.KCommonDAO;
import com.kadron.dao.KImageDAO;
import com.kadron.dao.KItemColorDAO;
import com.kadron.dao.KItemMaterialDAO;
import com.kadron.dao.KItemSizeDAO;
import com.kadron.dao.KPriceDAO;
import com.kadron.entity.Application;
import com.kadron.entity.Currency;
import com.kadron.entity.Item;
import com.kadron.entity.ItemColor;
import com.kadron.entity.ItemMaterial;
import com.kadron.entity.ItemSize;
import com.kadron.entity.ItemType;
import com.kadron.entity.KItemImage;
import com.kadron.entity.Price;
import com.kadron.exceptions.UploadImageException;
import com.kadron.manager.KMessageManager;
import com.kadron.manager.KSelection;

@AutoCreate
@Name("kItemManager")
@Scope(ScopeType.PAGE)
public class KItemManager extends KMessageManager implements Serializable,FileUploadListener,ValueChangeListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8898475863804949771L;

	private static final Log log = LogFactory.getLog(KItemManager.class);
	
	private Item item; 
	private List<KItemImage> images = new LinkedList<KItemImage>();
	private List<SelectItem> applications = new ArrayList<SelectItem>();
	private List<SelectItem> itemTypes = new ArrayList<SelectItem>();
	private List<Currency> currencies = new ArrayList<Currency>();
	
	private List<ItemColor> colors = new LinkedList<ItemColor>();
	private List<ItemSize> sizes = new LinkedList<ItemSize>();
	private List<ItemMaterial> materials = new LinkedList<ItemMaterial>();
	
	private long oldItemTypeId;
	private long applicationId;
	private long itemTypeId;
	private String klang = "EN";
	
	private KItemPrices kiPrices;
	
	@In
	private KCommonDAO commonDAO;
	@In
	private KPriceDAO priceDAO;
	@In
	private KImageDAO imageDAO;
	@In
	private KItemColorDAO itemColorDAO;
	@In
	private KItemMaterialDAO itemMaterialDAO;
	@In
	private KItemSizeDAO itemSizeDAO;
	
	
	@Create
	public void init() {
		String lang = (String) Component.getInstance("klang");
		if (!KUtil.isEmpty(lang)) {
			klang = lang;
		}
		Long itemId = (Long) Component.getInstance("itemId");
		if (itemId == null) {
			itemId = new Long(0);
		}
		loadData(itemId, klang);
	}
	
	private void loadData(long itemId,String klang) {
		images.clear();
		currencies = commonDAO.getAll(Currency.class);
		List<Application> apps = commonDAO.getAll(Application.class);
		for (Application e : apps) {
			SelectItem selectItem = new SelectItem(e.getId(), e.getName(klang));
			applications.add(selectItem);
		}
		List<ItemType> its = commonDAO.getAll(ItemType.class);
		for (ItemType e : its) {
			SelectItem selectItem = new SelectItem(e.getId(), e.getName(klang));
			itemTypes.add(selectItem);
		}
		if (itemId > 0) {
			item = (Item) commonDAO.find(itemId, Item.class);
			images = imageDAO.getItemImages(itemId);
			oldItemTypeId = itemTypeId = item.getItemType().getId();
			applicationId = item.getApplication().getId();
			loadP(item.getId());
		} else {
			item = new Item();
		}
		kiPrices = new KItemPrices(item, priceDAO);
	}
	
	public List<SelectItem> getApplications() {
		return applications;
	}

	public List<SelectItem> getItemTypes() {
		return itemTypes;
	}

	public List<ItemColor> getColors() {
		return this.colors;
	}
	
	private void loadP(long itemId) {
		colors.clear();
		sizes.clear();
		materials.clear();
		colors = itemColorDAO.getItemColor(item.getId());
		sizes = itemSizeDAO.getItemSize(itemId);
		materials = itemMaterialDAO.getItemMaterial(itemId);
	}
	
	public String save() {
		if (item == null) {
			bad(KConst.BAD_THING);
			return null;
		}
		if (log.isDebugEnabled()) {
			log.debug("Save Item itemId="+item.getId());
		}
		Application application = commonDAO.find(applicationId, Application.class);
		ItemType itemType = commonDAO.find(itemTypeId, ItemType.class);
		item.setApplication(application);
		item.setItemType(itemType);
		item = (Item) commonDAO.update(item);
		for (Currency c : kiPrices.getPriceMap().keySet()) {
			KPriceData p = kiPrices.get(c);
			Price price = priceDAO.find(item.getId(), p.getCurrencyId());
			if (p.getPrice() != null && p.getPrice() > 0) {
				if (price == null) {
					price = new Price(item, c);
				}
				price.setPrice(p.getPrice());
				price = (Price) commonDAO.update(price);				
			} else {
				if (price != null) {
					commonDAO.delete(price);					
				}
			}
		}
		if (oldItemTypeId>0 && itemTypeId != oldItemTypeId) {
			for (KItemImage img : images) {
				img.setColor(null);
				commonDAO.update(img);
			}
			for (ItemColor e : colors) {
				commonDAO.delete(e.getId(), ItemColor.class);
			}
			for (ItemSize e : sizes) {
				commonDAO.delete(e.getId(), ItemSize.class);
			}
			for (ItemMaterial e : materials) {
				commonDAO.delete(e.getId(), ItemMaterial.class);
			}
		}
		good();
		return "item";
	}

	public Item getItem() {
		return item;
	}

	public void setItem(Item item) {
		this.item = item;
	}

	public List<KItemImage> getImages() {
		return images;
	}

	public void setImages(List<KItemImage> images) {
		this.images = images;
	}

	public long getApplicationId() {
		return applicationId;
	}

	public void setApplicationId(long applicationId) {
		this.applicationId = applicationId;
	}

	public long getItemTypeId() {
		return itemTypeId;
	}

	public void setItemTypeId(long itemTypeId) {
		this.itemTypeId = itemTypeId;
	}

	public List<Currency> getCurrencies() {
		return currencies;
	}

	@Override
	public void processUpload(UploadEvent arg0) {
		UploadItem uploadItem = arg0.getUploadItem();
		if (uploadItem == null) {
			bad(KConst.BAD_THING);
			return;
		}
		int size = uploadItem.getFileSize();
		if (size > 1024000) {
			bad(KConst.BAD_THING);
			return;
		}
		String itemName = uploadItem.getFileName();
		byte[] data = new byte[4096];
		FileOutputStream outputStream = null;
		FileInputStream inputStream = null;
		String strDirectory = "";
		String imgPath = "";
		KItemImage image = new KItemImage(item.getId());
		UserTransaction transaction = null;
		try {
			transaction = Transaction.instance();
			strDirectory = KInitParams.WEBAPPS_PATH+KInitParams.IMG_PATH+"/i_"+item.getId();							
			imgPath = KInitParams.IMG_PATH+"/i_"+item.getId()+"/";							
			File directory = new File(strDirectory);
			if (!directory.exists()) {
				directory.mkdir();
			}
			
			String uuid = KIDGenerator.createUUID();
			image.setPath(imgPath);
			
			int IndexOf = itemName.lastIndexOf(".");
			String domainName = itemName.substring(IndexOf);
			if (log.isDebugEnabled()) {
				log.debug("domainName: " + domainName);							
			}
			if (KUtil.isEmpty(domainName)) {
				throw new UploadImageException("Domain name je prazno");
			} else if (!domainName.equalsIgnoreCase(".png") 
						&& !domainName.equalsIgnoreCase(".jpg")
						&& !domainName.equalsIgnoreCase(".JPG")
						&& !domainName.equalsIgnoreCase(".JPEG")
						) {
				throw new UploadImageException("Domain Name nije odgovarajuce");
			}
			String finalimage = uuid+domainName;
			if (log.isDebugEnabled()) {
				log.debug("Final Image===" + finalimage);							
			}
			
			image.setName(finalimage);
			image.setThumb(finalimage);//Default same thumb as image
			if (images == null || images.isEmpty()) {
				image.setMain(true);
			}
			image = (KItemImage) commonDAO.update(image);
			
			File file = new File(strDirectory+"/"+finalimage);
			outputStream = new FileOutputStream(file,true);
			inputStream = new FileInputStream(uploadItem.getFile());
			if (!file.exists()) {
				file.createNewFile();
				
			}
			int bit;
			while ((bit = inputStream.read(data)) != -1) {
				outputStream.write(data,0,bit);
			}
			inputStream.close();
			outputStream.flush();
			outputStream.close();
			transaction.commit();
			good();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				if (transaction != null) {					
					transaction.rollback();
				}
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		} finally {
			try {
				inputStream.close();
				outputStream.close();				
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	public void uploadThumb(UploadEvent arg0) {
		UploadItem uploadItem = arg0.getUploadItem();
		if (uploadItem == null) {
			bad(KConst.BAD_THING);
			return;
		}
		int size = uploadItem.getFileSize();
		Long imageId = (Long) arg0.getComponent().getAttributes().get("imageId");
		if (size > 1024000 || imageId == null || imageId <= 0) {
			bad(KConst.BAD_THING);
			return;
		}
		KItemImage kai = commonDAO.find(imageId, KItemImage.class);
		String itemName = uploadItem.getFileName();
		byte[] data = new byte[4096];
		FileOutputStream outputStream = null;
		FileInputStream inputStream = null;
		String strDirectory = "";
		String imgPath = "";
		UserTransaction transaction = null;
		try {
			transaction = Transaction.instance();
			strDirectory = KInitParams.WEBAPPS_PATH+KInitParams.IMG_PATH+"/i_"+item.getId();							
			imgPath = KInitParams.IMG_PATH+"/i_"+item.getId()+"/";							
			if (log.isDebugEnabled()) {
				log.debug("Image Path="+imgPath);
			}
			File directory = new File(strDirectory);
			if (!directory.exists()) {
				directory.mkdir();
			}
			
			String uuid = "t_"+KIDGenerator.createUUID();
			
			int IndexOf = itemName.lastIndexOf(".");
			String domainName = itemName.substring(IndexOf);
			if (log.isDebugEnabled()) {
				log.debug("domainName: " + domainName);							
			}
			if (KUtil.isEmpty(domainName)) {
				throw new UploadImageException("Domain name je prazno");
			} else if (!domainName.equalsIgnoreCase(".png") 
					&& !domainName.equalsIgnoreCase(".jpg")
					&& !domainName.equalsIgnoreCase(".JPG")
					&& !domainName.equalsIgnoreCase(".JPEG")
			) {
				throw new UploadImageException("Domain Name nije odgovarajuce");
			}
			String finalimage = uuid+domainName;
			if (log.isDebugEnabled()) {
				log.debug("Final Image===" + finalimage);							
			}
			
			kai.setThumb(finalimage);
			kai = (KItemImage) commonDAO.update(kai);
			
			File file = new File(strDirectory+"/"+finalimage);
			outputStream = new FileOutputStream(file,true);
			inputStream = new FileInputStream(uploadItem.getFile());
			if (!file.exists()) {
				file.createNewFile();
				
			}
			int bit;
			while ((bit = inputStream.read(data)) != -1) {
				outputStream.write(data,0,bit);
			}
			inputStream.close();
			outputStream.flush();
			outputStream.close();
			transaction.commit();
			good();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				if (transaction != null) {					
					transaction.rollback();
				}
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			bad(KConst.BAD_THING);
		} finally {
			try {
				inputStream.close();
				outputStream.close();				
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	public void mainImg(KItemImage img) {
		imageDAO.updateItemImageNotMain(img.getItemId());
		img.setMain(true);
		commonDAO.update(img);
		loadData(item.getId(), klang);
		good();
	}
	
	public void deleteImg(KItemImage img) {
		if (img == null) {
			bad(KConst.BAD_THING);
			return;
		}
		UserTransaction transaction = null;
		try {
			transaction = Transaction.instance();
			img = commonDAO.find(img.getId(), KItemImage.class);
			String strDirectory = KInitParams.WEBAPPS_PATH+KInitParams.IMG_PATH+"/i_"+item.getId();
			File file = new File(strDirectory+"/"+img.getName());
			File thumb = new File(strDirectory+"/"+img.getThumb());
			if (file.exists()) {
				boolean deleted = file.delete();
				if (!deleted) {
					log.error("Not deleted File: "+strDirectory+"/"+img.getName());
					bad("Not deleted File: "+strDirectory+"/"+img.getName());
					return;
				}
			}
			if (thumb.exists()) {
				boolean deleted = thumb.delete();
				if (!deleted) {
					log.error("Not deleted THUMB File: "+strDirectory+"/"+img.getThumb());
					bad("Not deleted THUMB File: "+strDirectory+"/"+img.getThumb());
					return;
				}
			}
			commonDAO.delete(img);
			transaction.commit();
			loadData(item.getId(), klang);
			good();			
		} catch (Exception e) {
			e.printStackTrace();
			if (transaction!=null) {
				try {
					transaction.rollback();					
				} catch (Exception e2) {
					log.error(e2);
				}
			}
		}
	}
	
	public void deleteThumb(KItemImage img) {
		if (img == null) {
			bad(KConst.BAD_THING);
			return;
		}
		UserTransaction transaction = null;
		try {
			transaction = Transaction.instance();
			img = commonDAO.find(img.getId(), KItemImage.class);
			String strDirectory = KInitParams.WEBAPPS_PATH+KInitParams.IMG_PATH+"/i_"+item.getId();
			File thumb = new File(strDirectory+"/"+img.getThumb());
			if (thumb.exists()) {
				boolean deleted = thumb.delete();
				if (!deleted) {
					log.error("Not deleted THUMB File: "+strDirectory+"/"+img.getThumb());
					bad("Not deleted THUMB File: "+strDirectory+"/"+img.getThumb());
					return;
				}
			}
			img.setThumb(null);
			commonDAO.update(img);
			transaction.commit();
			loadData(item.getId(), klang);
			good();			
		} catch (Exception e) {
			e.printStackTrace();
			if (transaction!=null) {
				try {
					transaction.rollback();					
				} catch (Exception e2) {
					log.error(e2);
				}
			}
		}
	}
	
	public void loadImages() {
		images = new LinkedList<KItemImage>();
		images = imageDAO.getItemImages(item.getId());
		loadP(item.getId());
	}

	@Override
	public void processValueChange(ValueChangeEvent arg0)
			throws AbortProcessingException {
		ItemColor color = (ItemColor) arg0.getNewValue();
		KItemImage img = (KItemImage) arg0.getComponent().getAttributes().get("img");
		if (img == null) {
			bad(KConst.BAD_THING);
			return;
		}
		img.setColor(color);
		commonDAO.update(img);
		loadData(item.getId(), klang);
		good();
	}
	
	public String avb() {
		if (item == null || item.getId() <= 0) {
			bad(KConst.BAD_THING);
			return null;
		}
		KSelection kselection = (KSelection) Component.getInstance("kSelection");
		kselection.setItemId(item.getId());
		return "e_item_available";
	}
	
	public String isItemSaved() {
		if (item == null || item.getId() <= 0) {
			bad(KConst.BAD_THING);
			return null;
		}
		KSelection kselection = (KSelection) Component.getInstance("kSelection");
		kselection.setItemId(item.getId());
		return "e_item_available";
	}

	public List<ItemSize> getSizes() {
		return sizes;
	}

	public List<ItemMaterial> getMaterials() {
		return materials;
	}

	public KItemPrices getKiPrices() {
		return kiPrices;
	}

}
